import React, { CSSProperties } from 'react'
import { Icon } from 'antd-mobile'
import ReactDOM from 'react-dom'
const PREFIX = 'gzwSelect'

export interface Option {
  label?: string
  value: string
  disabled?: boolean
}
interface Props {
  options: Option[]
  value?: string
  disabled?: boolean
  placeholder?: string
  onChange?: Function
  style?: React.CSSProperties
  position?: 'top' | 'bottom' | 'right'| 'left'
}
class Select extends React.Component<Props, any> {
  ref: HTMLDivElement | null
  mask: HTMLDivElement | null
  constructor(props: Props) {
    super(props)
    const { value } = props
    this.state = {
      value,
      disabled: props.disabled || false,
      visible: false
    }
    this.ref = null
    this.mask = null
  }
  getLabel(value: string = '') {
    const { options, placeholder } = this.props
    let label = placeholder
    if (value === '') return label
    options.some((v) => {
      if (v.value === value) {
        label = v.label || v.value
        return true
      }
      return false
    })
    return label
  }
  getClassName(className: string = '') {
    return `${PREFIX}${className}`
  }
  closeMask() {
    if (this.mask) {
      document.body.removeChild(this.mask)
      this.mask = null
    }
  }
  componentWillUnmount() {
    this.closeMask()
  }
  getTipPos(rect: DOMRect, position: string):CSSProperties {
    const { top, left, width, height } = rect
    const body = document.body.getBoundingClientRect()
    switch (position) {
      case 'top':
        if (body.width - left - width < width) {
          return {
            right: `${(width * 3) / 4}px`,
            top: `${ top + height / 2 - 28}px`
          }
        }
        if (left < width) {
          return {
            left: `${(width * 3) / 4}px`,
            top: `${ top + height / 2 - 28}px`
          }
        }
        return {
          top: `${top - 24}px`,
          left: `${left + width / 2 - 7}px`
        }
      case 'right':
        if (body.width - left - width < width) {
          return {
            right: `${(width * 3) / 4}px`,
            top: `${ top + height / 2 - 14}px`
          }
        }
        return {
          left: `${left + width - 4}px`,
          top: `${ top + height / 2 - 14}px`
        }
      case 'left':
        return {
          right: `${body.width - left - 14}px`,
          top: `${ top + height / 2 - 14}px`
        }
      default:
        if (body.width - left - width < width) {
          return {
            right: `${(width * 3) / 4}px`,
            top: `${ top + height - 10}px`
          }
        }
        if (left < width) {
          return {
            left: `${(width * 3) / 4}px`,
            top: `${ top + height - 10}px`
          }
        }
        return {
          top: `${top + height - 4}px`,
          left: `${left + width / 2 - 14}px`
        }
    }
  }
  getOptionPos(rect: DOMRect, position: string):CSSProperties {
    const { top, left, height, width } = rect
    const body = document.body.getBoundingClientRect()
    switch (position) {
      case 'top':
        if (body.width - left - width < width) {
          return {
            right: `${(width * 3) / 4 - 14}px`,
            top: `${ top + height / 2 - 24}px`,
            transform: 'translateY(-100%)'
          }
        }
        if (left < width) {
          return {
            left: `${(width * 3) / 4 - 14}px`,
            top: `${ top + height / 2 - 24}px`,
            transform: 'translateY(-100%)'
          }
        }
        return {
          top: `${top - 20}px`,
          left: `${left}px`,
          transform: 'translateY(-100%)'
        }
      case 'right':
        return {
          left: `${left + width + 20}px`,
          top: `${ top + height / 2 - 14}px`,
          transform: 'translateY(-50%)'
        }
      case 'left':
        return {
          right: `${body.width - left + 10}px`,
          top: `${top}px`,
          transform: 'translateY(-50%)'
        }
      default:
        if (body.width - left - width < width) {
          return {
            right: `${(width * 3) / 4 - 14}px`,
            top: `${ top + height + 14}px`
          }
        }
        if (left < width) {
          return {
            left: `${(width * 3) / 4 - 14}px`,
            top: `${ top + height + 14}px`
          }
        }
        return {
          top: `${top + height + 20}px`,
          left: `${left}px`
        }
    }
  }
  getPosition(rect: DOMRect, position: string) {
    const { top, height } = rect
    const body = document.body.getBoundingClientRect()
    const bottomHeight = body.height - top - height
    if (top > 260) {
      return 'top'
    }
    if (bottomHeight > 260) {
      return 'bottom'
    }
    switch (position) {
      case 'top':
        if (top >= 260) {
          return position
        }
        return 'bottom'
      case 'bottom':
        if (bottomHeight >= 260) {
          return position
        }
        return 'top'
      default:
        return position
    }
  }
  createMask() {
    const { value } = this.state
    const { options, onChange, position = 'bottom' } = this.props
    this.mask = document.createElement('div')
    const rect = this.ref?.getBoundingClientRect()
    if (rect) {
      const mask = <div className={this.getClassName('Mask')} onClick={() => {
        this.closeMask()
      }}>
        <div className={this.getClassName(`TipIcon ${this.getPosition(rect, position)}`)} style={this.getTipPos(rect, this.getPosition(rect, position))}></div>
        <div className={this.getClassName('Options')} style={this.getOptionPos(rect, this.getPosition(rect, position))}>
          {
            options.map((v, index) => <div key={index} className={this.getClassName(value === v.value ? 'Item checked' : 'Item')} onClick={(e) => {
              e.stopPropagation()
              this.setState({
                value: v.value
              }, () => {
                this.setState({
                  visible: false
                })
                typeof onChange === 'function' && onChange(v.value)
                this.closeMask()
              })
            }}>
              <span>{v.label || v.value}</span>
            </div>)
          }
        </div>
      </div>
      ReactDOM.render(mask, this.mask)
      document.body.appendChild(this.mask)
    }
  }
  render() {
    const { visible } = this.state
    const { style, value } = this.props
    return (
      <div className={this.getClassName(visible ? ' active' : '')} style={style} ref={ref => { this.ref = ref }}>
        <div className={this.getClassName('Wrapper')}>
          <div className={this.getClassName('Content')} onClick={(e) => {
            e.stopPropagation()
            this.setState({
              visible: !visible
            })
            this.createMask()
          }}>
            <div className={this.getClassName('Label')}>
              {
                this.getLabel(value)
              }
            </div>
            <Icon type={'down'} style={{ width: '12px', height: '12px' }} className={'icon'}></Icon>
          </div>
        </div>
      </div>
    )
  }
}

export default Select
